package com.oig.sys.msg.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.oig.common.exception.BadRequestException;
import com.oig.sys.msg.constants.MsgEnums;
import com.oig.sys.msg.dao.ITbTaskDao;
import com.oig.sys.msg.dto.TaskDto;
import com.oig.sys.msg.entity.TbTask;
import com.oig.sys.msg.service.ITbTaskLogService;
import com.oig.sys.msg.service.ITbTaskService;
import com.oig.sys.msg.vo.TaskVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;

/**
 * @author wuxl
 */
@Service
public class TbTaskServiceImpl implements ITbTaskService {

	private final ITbTaskDao tbTaskDao;
	private final ITbTaskLogService taskLogService;

	@Autowired
	public TbTaskServiceImpl(ITbTaskDao tbTaskDao,
							 ITbTaskLogService taskLogService){
		 this.tbTaskDao = tbTaskDao;
		 this.taskLogService = taskLogService;
	}

	@Transactional
	@Override
	public TaskVo addTask(TaskDto taskDto){
		TbTask task = new TbTask();
		BeanUtils.copyProperties(taskDto, task, "id");
		if (task.getPlanStartTime()==null){
			task.setPlanStartTime(new Date());
		}
		if (task.getTaskHours()==null){
			task.setTaskHours(BigDecimal.ZERO);
		}
		if (StringUtils.isBlank(task.getTaskPriority())){
			task.setTaskPriority(MsgEnums.TaskPriority.MID.getCode());
		}
		if (StringUtils.isBlank(task.getTaskLevel())){
			task.setTaskLevel(MsgEnums.TaskLevel.MID.getCode());
		}
		task.setStatus(MsgEnums.TaskStatus.INIT.getCode());
		task.setLastUpdateName(task.getCreateUserName());
		task.setLastUpdateId(task.getCreateUserId());
		task.setLastUpdateTime(task.getCreateTime());
		this.tbTaskDao.save(task);
		this.taskLogService.addCreateLog(task);
		return this.buildVo(task);
	}

	private TaskVo buildVo(TbTask task){
		TaskVo taskVo = new TaskVo();
		BeanUtils.copyProperties(task, taskVo);
		return taskVo;
	}


	@Transactional
	@Override
	public TaskVo updateTask(TaskDto taskDto){
		TbTask task = this.tbTaskDao.getTaskById(taskDto.getId());
		if (MsgEnums.TaskStatus.FINISH.getCode().equals(task.getStatus())){
			throw new BadRequestException("任务已完成,不能修改") ;
		}
		TbTask oldTask = ObjectUtil.clone(task);
		BeanUtils.copyProperties(taskDto, task, "status","tenantId","tenantName","watchId","watchName");
		this.tbTaskDao.save(task);
		if (!taskDto.getTaskContent().equals(task.getTaskContent())
				||!taskDto.getTaskTitle().equals(task.getTaskTitle())
				||!taskDto.getDealId().equals(task.getDealId())){
			this.taskLogService.addUpdateLog(oldTask, task);
		}
		return this.buildVo(task);
	}

	@Transactional
	@Override
	public void deleteTask(Integer id){
		TbTask task = this.tbTaskDao.getTaskById(id);
		if (!MsgEnums.TaskStatus.INIT.getCode().equals(task.getStatus())){
			throw new BadRequestException("任务已开始，不能删除只能关闭") ;
		}
		this.tbTaskDao.delete(task);
	}

	@Override
	public TaskVo getTaskMainInfo(Integer id) {
		TbTask task = this.tbTaskDao.getTaskById(id);
		if (task==null) return null;
		return this.buildVo(task);
	}

	@Override
	public TaskVo getTask(Integer id) {
		TbTask task = this.tbTaskDao.getTaskById(id);
		if (task==null){
			throw new BadRequestException("任务不存在");
		}
		TaskVo taskVo = this.buildVo(task);
		taskVo.setTaskLogVoList(this.taskLogService.findAllLogByTaskId(id));
		return taskVo;
	}

	@Transactional
	@Override
	public void startTask(TaskDto taskDto) {
		TbTask task = this.tbTaskDao.getTaskById(taskDto.getId());
		this.checkOptRole(taskDto.getLastUpdateId(), task);
		task.setStatus(MsgEnums.TaskStatus.DOING.getCode());
		task.setStartTime(taskDto.getStartTime());
		if (task.getStartTime()==null){
			task.setStartTime(new Date());
		}
		task.setLastUpdateId(taskDto.getLastUpdateId());
		task.setLastUpdateName(taskDto.getLastUpdateName());
		task.setLastUpdateTime(taskDto.getLastUpdateTime());
		this.tbTaskDao.save(task);
	}

	@Transactional
	@Override
	public void finishTask(TaskDto taskDto) {
		TbTask task = this.tbTaskDao.getTaskById(taskDto.getId());
		this.checkOptRole(taskDto.getLastUpdateId(), task);
		task.setLastUpdateId(taskDto.getLastUpdateId());
		task.setLastUpdateName(taskDto.getLastUpdateName());
		task.setLastUpdateTime(taskDto.getLastUpdateTime());
		task.setStatus(MsgEnums.TaskStatus.FINISH.getCode());
		task.setUsedHours(taskDto.getUsedHours());
		task.setFinishTime(taskDto.getFinishTime());
		task.setStartTime(taskDto.getStartTime());
		if (task.getStartTime()==null){
			task.setStartTime(task.getPlanStartTime());
		}
		if (task.getFinishTime()==null){
			task.setFinishTime(new Date());
		}
		if (task.getUsedHours()==null&&task.getStartTime()!=null){
			DateUtil.between(task.getStartTime(), task.getFinishTime(), DateUnit.HOUR);
		}
		this.tbTaskDao.save(task);
		taskLogService.addFinishLog(task, taskDto.getLogRemark());
	}

	private void checkOptRole(Integer userId, TbTask task){
		if (task==null){
			throw new BadRequestException("任务不存在") ;
		}
		if (MsgEnums.TaskStatus.FINISH.getCode().equals(task.getStatus())
				||MsgEnums.TaskStatus.CLOSE.getCode().equals(task.getStatus())){
			throw new BadRequestException("任务已完成或已关闭") ;
		}
		if (!userId.equals(task.getDealId())){
			throw new BadRequestException("无权操作完成") ;
		}
	}

	@Transactional
	@Override
	public void assignTask(TaskDto taskDto) {
		TbTask task = this.tbTaskDao.getTaskById(taskDto.getId());
		this.checkOptRole(taskDto.getLastUpdateId(), task);
		task.setDealId(taskDto.getDealId());
		task.setDealName(taskDto.getDealName());
		task.setLastUpdateId(taskDto.getLastUpdateId());
		task.setLastUpdateName(taskDto.getLastUpdateName());
		task.setLastUpdateTime(taskDto.getLastUpdateTime());
		this.tbTaskDao.save(task);
		taskLogService.addAssignLog(task, taskDto.getLogRemark());
	}

	@Transactional
	@Override
	public void refuseTask(TaskDto taskDto) {
		TbTask task = this.tbTaskDao.getTaskById(taskDto.getId());
		this.checkOptRole(taskDto.getLastUpdateId(),task);
		task.setDealId(task.getWatchId());
		task.setDealName(task.getWatchName());
		task.setLastUpdateId(taskDto.getLastUpdateId());
		task.setLastUpdateName(taskDto.getLastUpdateName());
		task.setLastUpdateTime(taskDto.getLastUpdateTime());
		task.setStatus(MsgEnums.TaskStatus.REFUSE.getCode());
		this.tbTaskDao.save(task);
		taskLogService.addRefuseLog(task, taskDto.getLogRemark());
	}

	@Transactional
	@Override
	public void closeTask(TaskDto taskDto) {
		TbTask task = this.tbTaskDao.getTaskById(taskDto.getId());
		if (MsgEnums.TaskStatus.CLOSE.getCode().equals(task.getStatus())){
			throw new BadRequestException("任务已关闭") ;
		}
		task.setLastUpdateId(taskDto.getLastUpdateId());
		task.setLastUpdateName(taskDto.getLastUpdateName());
		task.setLastUpdateTime(taskDto.getLastUpdateTime());
		task.setStatus(MsgEnums.TaskStatus.CLOSE.getCode());
		this.tbTaskDao.save(task);
		taskLogService.addCloseLog(task, taskDto.getLogRemark());
	}

	@Transactional
	@Override
	public void openTask(TaskDto taskDto) {
		TbTask task = this.tbTaskDao.getTaskById(taskDto.getId());
		if (!MsgEnums.TaskStatus.CLOSE.getCode().equals(task.getStatus())){
			throw new BadRequestException("任务非关闭状态") ;
		}
		task.setStatus(MsgEnums.TaskStatus.DOING.getCode());
		task.setLastUpdateId(taskDto.getLastUpdateId());
		task.setLastUpdateName(taskDto.getLastUpdateName());
		task.setLastUpdateTime(taskDto.getLastUpdateTime());
		this.tbTaskDao.save(task);
		taskLogService.addOpenLog(task, taskDto.getLogRemark());
	}

	@Override
	public Integer findUnDoSizeByUserId(Integer userId) {
		return this.tbTaskDao.countUndoByDealId(userId);
	}

	@Override
	public Integer findFinishTaskSizeByUserId(Integer userId) {
		return this.tbTaskDao.countFinishTaskSizeByUserId(userId, DateUtil.beginOfWeek(new Date(), true));
	}
}
